{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Using AXI GPIO with PYNQ\n",
    "\n",
    "## Goal\n",
    "\n",
    "The aim of this notebook is to show how to use AXI GPIO from PYNQ. \n",
    "\n",
    "Multiple AXI GPIO controllers can be implemented in the programmable logic and used to control internal or external GPIO signals.\n",
    "\n",
    "## Hardware design\n",
    "\n",
    "This example uses a bitstream that connects three AXI GPIO controllers to the LEDs, buttons, and switches and can be used with the PYNQ-Z1 or PYNQ-Z2 board. (Each AXI GPIO controller has 2 channels, so multiple peripherals could be controlled from one AXI GPIO IP, but for simplicity and demonstration purposes, separate AXI GPIO controllers are used. \n",
    "\n",
    "![AXI GPIO Design](./images/axi_gpio_design.png \"AXI GPIO Design\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1. Download the tutorial overlay\n",
    "\n",
    "The `axi_gpio.bit` and `axi_gpio.hwh` files can be found in the bitstreams directory local to this folder. \n",
    "The bitstream can be downloaded by passing the relative path to the Overlay class. "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* Check the bitstream and .tcl exists in the bitstream directory"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "!dir ./bitstream/axi_gpio.*"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* Download the bitstream"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from pynq import Overlay\n",
    "axi_gpio_design = Overlay(\"./bitstream/axi_gpio.bit\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Check the IP Dictionary for this design. The IP dictionary lists AXI IP in the design, and for this example will list the AXI GPIO controllers for the buttons, leds, and switches. The Physical address, the address range and IP type will be listed. If any interrupts, or GPIO were connected to the PS, they would also be reported. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "axi_gpio_design.ip_dict"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "hex(axi_gpio_design.ip_dict[\"buttons\"][\"phys_addr\"])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## AxiGPIO class\n",
    "\n",
    "The PYNQ AxiGPIO class will be used to access the AXI GPIO controllers. "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1. Controlling the switches and push-buttons\n",
    "\n",
    "The instances can be found and referenced from the IP dictionary. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from pynq.lib import AxiGPIO\n",
    "\n",
    "buttons_instance = axi_gpio_design.ip_dict['buttons']\n",
    "buttons = AxiGPIO(buttons_instance).channel1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "buttons.read()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The buttons controller is connected to all four user push-buttons on the board (BTN0 to BTN3). Try pressing any combination of the buttons and rerunning the cell above.\n",
    "\n",
    "The AXI GPIO controller for the switches can be used in a similar way:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "switches_instance = axi_gpio_design.ip_dict['switches']\n",
    "switches = AxiGPIO(switches_instance).channel1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(f\"Switches: {switches.read()}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2. Controlling the LEDs\n",
    "\n",
    "The LEDs can be used in a similar way. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from pynq.lib import AxiGPIO\n",
    "led_instance = axi_gpio_design.ip_dict['leds']\n",
    "led = AxiGPIO(led_instance).channel1"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The outputs can be addressed using a slice. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "led[0:4].write(0x1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from time import sleep\n",
    "\n",
    "led[0:4].write(0x3)\n",
    "sleep(1)\n",
    "led[0:4].write(0x7)\n",
    "sleep(1)\n",
    "led[0:4].write(0xf)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* Reset the LEDs"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "led[0:4].off()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3 Putting it together\n",
    "\n",
    "Run a loop to set the LEDs to the value of the pushbuttons. \n",
    "\n",
    "Before executing the next cell, make sure Switch 0 (SW0) is \"on\". While the loop is running, press a push-button and notice the corresponding LED turns on. To exist the loop, change Switch 0 to off. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "while(switches.read() is 1):\n",
    "    led[0:4].write(buttons.read())"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
